package scalalang.reflection

import scala.reflect.runtime.universe._
import scala.tools.reflect.ToolBox
import scala.reflect.ClassTag
object MacrosTest extends App {
  //  Print.printf("hello %s!", "world") //需要先让macro编译 得使用sbt子模块

  trait Showable[T] { def show(x: T): String }
  def show[T](x: T)(implicit s: Showable[T]) = s.show(x)
  implicit object IntShowable extends Showable[Int] {
    def show(x: Int) = x.toString
  }
  show(42)

  //  val ttt = TypeWork.t
  // ttt.a

  println
  val tb = runtimeMirror(getClass.getClassLoader).mkToolBox()
  val sss = "sdfsdfsdf"
  val tree = reify {

    sss
    "123123"
    println("1" + 1 + "234234")
    "sss" * 10
    val g = "sss" * 10

    def pack[T](t: T) = {

      t match {
        case s: String => println(s)
        case _ =>
      }
      t
    }
    object T

    new String("")
    pack(T)
    pack { sss }
    pack { "123123" }
    pack { println("1" + 1 + "234234") }
    pack { "sss" * 10 }
    pack { val g = "sss" * 10 }

    //pack(T)
  }.tree
  (tree.children).foreach { t =>

    println(showRaw(t))
  }
  println
  val pfn: PartialFunction[Any, String] = { case s: String => s }
  reify {
    pfn

    val pfn2: PartialFunction[String, String] = { case s => s }
  }.tree.children.foreach { t =>

    println(showRaw(t))
  }
  trait TTT
  println()
  val Block(stats, expr) = reify {

    object Collect {
      var result = scala.collection.mutable.Buffer[String]()
      val pfn2 = { case s: String => s }: PartialFunction[Any, String]
      def apply[T](t: T) = {
        Option(t).collect(pfn2).foreach { t => result += t }
        t
      }
      def apply2[T](t: T) = {
        Option(t).collect(pfn).foreach { t => result += t }
        t
      }
    }
    val (s1, s2, s3) = ("1", "2", "3")
    sss
    "123123"
    println("1" + 1 + "234234")
    "sss" * 10
    val g = "sss" * 10

    object TTTTTTTTTTTTTTT extends TTT
    //    Collect
    Collect(TTTTTTTTTTTTTTT)

    new String("")

    Collect { sss }
    Collect { "123123" }
    println("1" + 1 + "234234")
    Collect { "sss" * 10 }
    val gg = Collect("sss" * 10)
    (0 to 10).map { t => "t" + t }
    scala.util.Try { "1111" }
    //pack(T)
  }.tree
  println("1111" * 300)
  (expr :: stats)
    .foreach { t =>

      println(showRaw(t))
    }

  println("1111" * 300)

  reify(1, 2, 3).tree.children.foreach { t =>

    println(showRaw(t))
  }

  println("*" * 300)
  //  println(t.tpe)
  //Block(
  //    List(
  //        Literal(Constant("123123")), 
  //        Apply(Select(Ident(scala.Predef), newTermName("println")), List(Apply(Select(Apply(Select(Literal(Constant("1")), newTermName("$plus")), List(Literal(Constant(1)))), newTermName("$plus")), List(Literal(Constant("234234"))))))
  //        ), 
  //        Apply(Select(Apply(Select(Ident(scala.Predef), newTermName("augmentString")), List(Literal(Constant("sss")))), newTermName("$times")), List(Literal(Constant(10))))
  //    )

  //  println(reify(showRaw().tree))
/*
  println((LineCollecter.collect {
    case s: String => (s) :: Nil
    case s: Iterable[String] => s
    case n: TTT => n.toString :: Nil
    //  case n=>n.toString::Nil
  } {
    {
    sss
    "123123"
    //    println("1" + 1 + "234234")
    "sss" * 10
    (0 to 10).toSeq.map { t =>
      //println(t)
      "t" + t
    }
    }
 val h=   {
    new String("")
    object TTTTTTTTTTTTTTT extends TTT
    }
    scala.util.Try { "1111" }

    "s1ss" * 10
  }).flatMap { locally })*/

  //println(  LineCollecter.collect { case s: String => s }(1,2))
  //  Apply(
  //      Apply(
  //          Select(Apply(Select(Apply(Select(Ident(scala.Predef), newTermName("intWrapper")), List(Literal(Constant(0)))), newTermName("to")), List(Literal(Constant(10)))), newTermName("map")), List(Function(List(ValDef(Modifiers(PARAM), newTermName("t"), TypeTree(), EmptyTree)), Apply(Select(Literal(Constant("t")), newTermName("$plus")), List(Ident(newTermName("t"))))))),
  //          List(Select(Ident(scala.collection.immutable.IndexedSeq), newTermName("canBuildFrom")))
  //      )

  //Apply(
  //    Apply(
  //        Select(Ident(scalalang.reflection.LineCollecter), newTermName("collect")), List(Typed(Block(List(ClassDef(Modifiers(FINAL | SYNTHETIC), newTypeName("$anonfun"), List(), Template(List(), emptyValDef, List(DefDef(Modifiers(), nme.CONSTRUCTOR, List(), List(List()), TypeTree(), Block(List(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())), Literal(Constant(())))), DefDef(Modifiers(OVERRIDE | FINAL | METHOD), newTermName("applyOrElse"), List(TypeDef(Modifiers(DEFERRED | PARAM), newTypeName("A1"), List(), TypeBoundsTree(TypeTree(), TypeTree())), TypeDef(Modifiers(DEFERRED | PARAM), newTypeName("B1"), List(), TypeBoundsTree(TypeTree(), TypeTree()))), List(List(ValDef(Modifiers(PARAM | SYNTHETIC | TRIEDCOOKING), newTermName("x4"), Ident(newTypeName("A1")), EmptyTree), ValDef(Modifiers(PARAM | SYNTHETIC), newTermName("default"), AppliedTypeTree(Ident(scala.Function1), List(Ident(newTypeName("A1")), Ident(newTypeName("B1")))), EmptyTree))), TypeTree(), Match(Annotated(Apply(Select(New(Ident(scala.unchecked)), nme.CONSTRUCTOR), List()), Typed(Select(Ident(newTermName("x4")), newTermName("asInstanceOf")), TypeTree())), List(CaseDef(Bind(newTermName("s"), Typed(Ident(nme.WILDCARD), Select(Ident(scala.Predef), newTypeName("String")))), EmptyTree, Ident(newTermName("s"))), CaseDef(Bind(newTermName("s"), Typed(Ident(nme.WILDCARD), AppliedTypeTree(Select(Ident(scala.package), newTypeName("Iterable")), List(Select(Ident(scala.Predef), newTypeName("String")))))), EmptyTree, Ident(newTermName("s"))), CaseDef(Bind(newTermName("o"), Ident(nme.WILDCARD)), EmptyTree, Ident(newTermName("o"))), CaseDef(Bind(newTermName("defaultCase$"), Ident(nme.WILDCARD)), EmptyTree, Apply(Select(Ident(newTermName("default")), newTermName("apply")), List(Ident(newTermName("x4")))))))), DefDef(Modifiers(FINAL | METHOD), newTermName("isDefinedAt"), List(), List(List(ValDef(Modifiers(PARAM | SYNTHETIC | TRIEDCOOKING), newTermName("x4"), TypeTree(), EmptyTree))), TypeTree(), Match(Annotated(Apply(Select(New(Ident(scala.unchecked)), nme.CONSTRUCTOR), List()), Typed(Select(Ident(newTermName("x4")), newTermName("asInstanceOf")), TypeTree())), List(CaseDef(Bind(newTermName("s"), Typed(Ident(nme.WILDCARD), Select(Ident(scala.Predef), newTypeName("String")))), EmptyTree, Literal(Constant(true))), CaseDef(Bind(newTermName("s"), Typed(Ident(nme.WILDCARD), AppliedTypeTree(Select(Ident(scala.package), newTypeName("Iterable")), List(Select(Ident(scala.Predef), newTypeName("String")))))), EmptyTree, Literal(Constant(true))), CaseDef(Bind(newTermName("o"), Ident(nme.WILDCARD)), EmptyTree, Literal(Constant(true))), CaseDef(Bind(newTermName("defaultCase$"), Ident(nme.WILDCARD)), EmptyTree, Literal(Constant(false)))))))))), Apply(Select(New(Ident(newTypeName("$anonfun"))), nme.CONSTRUCTOR), List())), TypeTree()))), List(Block(List(Select(This(newTypeName("MacrosTest")), newTermName("sss")), Literal(Constant("123123")), Apply(Select(Apply(Select(Ident(scala.Predef), newTermName("augmentString")), List(Literal(Constant("sss")))), newTermName("$times")), List(Literal(Constant(10)))), Apply(Apply(Select(Select(Apply(Select(Apply(Select(Ident(scala.Predef), newTermName("intWrapper")), List(Literal(Constant(0)))), newTermName("to")), List(Literal(Constant(10)))), newTermName("toSeq")), newTermName("map")), List(Function(List(ValDef(Modifiers(PARAM), newTermName("t"), TypeTree(), EmptyTree)), Apply(Select(Literal(Constant("t")), newTermName("$plus")), List(Ident(newTermName("t"))))))), List(Select(Ident(scala.collection.immutable.IndexedSeq), newTermName("canBuildFrom")))), Apply(Select(Ident(scala.util.Try), newTermName("apply")), List(Literal(Constant("1111")))), Apply(Select(Apply(Select(Ident(scala.Predef), newTermName("augmentString")), List(Literal(Constant("s1ss")))), newTermName("$times")), List(Literal(Constant(10))))), Block(List(Literal(Constant(""))), Literal(Constant(()))))
  //            )
  //    )
}